Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
Components.utils.import("resource://app/jsmodules/sbLibraryUtils.jsm");



// Shorthand
if (typeof(Cc) == "undefined") 
    var Cc = Components.classes;
if (typeof(Ci) == "undefined") 
    var Ci = Components.interfaces;
if (typeof(Cu) == "undefined") 
    var Cu = Components.utils;
if (typeof(Cr) == "undefined") 
    var Cr = Components.results;

const Msg = Cu.reportError;
//const Msg = alert;
//function Msg(x){}

// check that gMM exists
if (typeof gMM == "undefined") {
    var gMM = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"].getService(Ci.sbIMediacoreManager);
}
if (typeof(gBrowser) == "undefined") 
    var gBrowser = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('Songbird:Main').gBrowser;

if (typeof(gXPath) == "undefined") 
    var gXPath = Cc["@mozilla.org/dom/xpath-evaluator;1"].createInstance(Ci.nsIDOMXPathEvaluator);


// Make a namespace.
if (typeof Lastbird == 'undefined') {
    var Lastbird = {};
}

if (typeof gCurrentPlaylist == 'undefined') {
    var gCurrentPlaylist = null;
}

// get the XPCOM service as a JS object
if (typeof gLFM == 'undefined') {
    gLFM = Components.classes['@songbirdnest.com/lastfm;1'].getService().wrappedJSObject;
}




/**
 * UI controller that is loaded into the main player window
 */
Lastbird.Controller = {

    /**
     * Called when the window finishes loading
     */
    onLoad: function(){
    
        // initialization code
        this._initialized = true;
        this._strings = document.getElementById("lastbird-strings");
        
        // Perform extra actions the first time the extension is run
        if (Application.prefs.get("extensions.lastbird.firstrun").value) {
            Application.prefs.setValue("extensions.lastbird.firstrun", false);
            this._firstRunSetup();
        }
        
        // init interfaces
        this._windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
        
        this.AddPlaylistCommands();
        gMM.addListener(Lastbird.Listener);
        var controller = this;
        
        this._Enable_lastbird = document.getElementById("lastbird-enable-cmd");
        this._Enable_lastbird.addEventListener("command", function(){
            controller.ToggleEnable();
        }, false);
        
        this._Enable_AD = document.getElementById("lastbird-use-artist-cmd");
        this._Enable_AD.addEventListener("command", function(){
            controller.ToggleEnableArtistDiscovery();
        }, false);
        
        this._Enable_TD = document.getElementById("lastbird-use-song-cmd");
        this._Enable_TD.addEventListener("command", function(){
            controller.ToggleEnableTrackDiscovery();
        }, false);
        
        
        if (controller.isEnabled()) 
            controller.Enable();
        else 
            controller.Disable();
        
        if (controller.isArtistDiscoveryEnabled()) 
            controller.EnableArtistDiscovery();
        else 
            controller.DisableArtistDiscovery();
        
        if (controller.isTrackDiscoveryEnabled()) 
            controller.EnableTrackDiscovery();
        else 
            controller.DisableTrackDiscovery();
        
        
    },
    
    
    /**
     * Called when the window is about to close
     */
    onUnLoad: function(){
        this._initialized = false;
        this._builder.shutdown();
    },
    GetSelectedMediaItems: function(){
    
        var mediaListView = gBrowser.currentMediaListView;
        
        if (mediaListView == null) {
            return null;
        }
        
        var selection = mediaListView.selection;
        var itemEnum = selection.selectedMediaItems;
        
        // Get the first selected item
        var items = [];
        while (itemEnum.hasMoreElements()) {
            items.push(itemEnum.getNext());
        }
        
        if (items.length == 0) {
            return null;
        }
        
        return items;
    },
    
    PlaySimilarArtists: function(){
    
        // get the selected tracks		
        var items = this.GetSelectedMediaItems();
        if (items == null || items.length == 0) {
            return;
        }
        
        // Get the first artist
        var artistName = items[0].getProperty(SBProperties.artistName);
        
        if (items.length > 1) 
            artistName += " & Others"
        
        // Create the playlist
        gCurrentPlaylist = this.CreatePlaylist(artistName + " Similar Artists");
        
        for (var i = 0; i < items.length; i++) {
            this.AppendTrack(items[i]);
        }
        
        this.SelectPlaylist(gCurrentPlaylist);
        gMM.sequencer.playView(gCurrentPlaylist.createView());
    },
    OnViewChanged: function(view)
	{
		// if it is named "some thing Similar artists"
		var selectedList =	view.mediaList;
		if(selectedList.name.toLowerCase().indexOf("now playing") > -1)
			return;
		var index = selectedList.name.toLowerCase().indexOf("similar artists");
		if(index > -1)
		{
			// then it is a lastbird list .. use it
			gCurrentPlaylist = selectedList;

				this.Enable();
		}	
		else
		{
			gCurrentPlaylist = null;
			this.Disable();
		}
	},
    AddPlaylistCommands: function(){
    
        // init interfaces
        this._commandsManager = Cc["@songbirdnest.com/Songbird/PlaylistCommandsManager;1"].getService(Ci.sbIPlaylistCommandsManager);
        // Get the root branch
        var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
        
        
        // create a command builder
        const PlaylistCommandsBuilder = new Components.Constructor("@songbirdnest.com/Songbird/PlaylistCommandsBuilder;1", "sbIPlaylistCommandsBuilder");
        this._builder = new PlaylistCommandsBuilder();
        
        this._builder.appendSeparator(null, "lastbird_separator_id");
        this._builder.appendAction(null, "lastbird_similar_artists_id", "Play Similar Artists", "creats a new list and plays it", function(){
            Lastbird.Controller.PlaySimilarArtists();
        });
        
        this._mainLibraryGUID = prefs.getComplexValue("songbird.library.main", Ci.nsISupportsString);
        this._mainLibCommandsBuilder = this._builder;
        
        //----------Add items to normal playlists
        // Get registered commands 
        var mainLibRegisteredCommands = this._commandsManager.getPlaylistCommandsMediaItem(this._mainLibraryGUID, "simple");
        
        // if there are registerd commands
        if (!mainLibRegisteredCommands || !mainLibRegisteredCommands.hasMoreElements()) {
            // insert them before LastBird commands
            this._mainLibCommandsBuilder.insertPlaylistCommandsBefore(null, "lastbird_separator_id", "defaultCommandSet1", this._commandsManager.request(kPlaylistCommands.MEDIAITEM_DEFAULT));
        }
        
        // register the new set of commands
        this._commandsManager.registerPlaylistCommandsMediaItem(this._mainLibraryGUID, "", this._mainLibCommandsBuilder);
        
        
        //----------Add items to simple playlists
        this._simplePlaylistsCommandsBuilder = this._builder;
        var simplePlaylistRegisteredCommands = this._commandsManager.getPlaylistCommandsMediaItem("", "simple");
        //this._simplePlaylistsCommandsBuilder.insertPlaylistCommandsBefore(null, "lastbird_separator_id", "defaultCommandSet2", this._commandsManager.request(kPlaylistCommands.MEDIAITEM_DEFAULT));
        this._commandsManager.registerPlaylistCommandsMediaItem("", "simple", this._simplePlaylistsCommandsBuilder);
        
        //----------Add items to smart playlists
        this._smartPlaylistsCommandsBuilder = this._builder;
        var smartPlaylistRegisteredCommands = this._commandsManager.getPlaylistCommandsMediaItem("", "smart");
        if (!smartPlaylistRegisteredCommands || !smartPlaylistRegisteredCommands.hasMoreElements()) {
            this._smartPlaylistsCommandsBuilder.insertPlaylistCommandsBefore(null, "lastbird_separator_id", "defaultCommandSet3", this._commandsManager.request(kPlaylistCommands.MEDIAITEM_SMARTPLAYLIST));
        }
        this._commandsManager.registerPlaylistCommandsMediaItem("", "smart", this._smartPlaylistsCommandsBuilder);
        
        
    },
    
    /**
     * Sample command action
     */
    OnTrackChanged: function(track){
        var artistName = track.getProperty(SBProperties.artistName);
        var trackName = track.getProperty(SBProperties.trackName);
        
        if (this._Enabled && gCurrentPlaylist != null) {
            this.ProcessTrack(artistName, trackName);
        }
    },
    
    ProcessTrack: function(artistName, trackName){
		if(this._ArtistDiscovery)
	        this.GetSimilarArtists(artistName);
		if(this._TrackDiscovery)
	        this.GetSimilarTracks(artistName, trackName);
    },
    
    AppendTrackByName: function(artistName, trackName){
        var newTrack = this.FindLocalSong(artistName, trackName);
        if (newTrack == null) 
            ;//Msg("track not found" + trackName + " " + artistName);
        else 
            this.AppendTrack(newTrack);
        
    },
    isEnabled: function(){
        return Application.prefs.get("extensions.lastbird.lbenabled").value;
    },
    Enable: function(){
        var item = document.getElementById("lastbird-enable-item");
        item.setAttribute("checked", "true");
        
        item = document.getElementById("lastbird-statusbarpanel");
        item.setAttribute("src", "chrome://lastbird/skin/audioscrobbler_red.png");
        
        Application.prefs.setValue("extensions.lastbird.lbenabled", true);
		this._Enabled = true;
    },
    Disable: function(){
        var item = document.getElementById("lastbird-enable-item");
        item.setAttribute("checked", "false");
        
        item = document.getElementById("lastbird-statusbarpanel");
        item.setAttribute("src", "chrome://lastbird/skin/audioscrobbler_grey.png");
        
        Application.prefs.setValue("extensions.lastbird.lbenabled", false);
		this._Enabled = false;
    },
    
    ToggleEnable: function(){
        if (this.isEnabled()) 
            this.Disable();
        else 
            this.Enable();
    },
    
    ToggleEnableArtistDiscovery: function(){
        if (this.isArtistDiscoveryEnabled()) 
            this.DisableArtistDiscovery();
        else 
            this.EnableArtistDiscovery();
    },
    ToggleEnableTrackDiscovery: function(){
        if (this.isTrackDiscoveryEnabled()) 
            this.DisableTrackDiscovery();
        else 
            this.EnableTrackDiscovery();
    },
    
    isArtistDiscoveryEnabled: function(){
        return Application.prefs.get("extensions.lastbird.lbaddartists").value;
    },
    EnableArtistDiscovery: function(){
        var item = document.getElementById("lastbird-artist-discovery-item");
        item.setAttribute("checked", "true");
        
        Application.prefs.setValue("extensions.lastbird.lbaddartists", true);
        this._ArtistDiscovery = true;
    },
    DisableArtistDiscovery: function(){
        var item = document.getElementById("lastbird-artist-discovery-item");
        item.setAttribute("checked", "false");
        
        Application.prefs.setValue("extensions.lastbird.lbaddartists", false);
        this._ArtistDiscovery = false;
    },
    
    isTrackDiscoveryEnabled: function(){
        return Application.prefs.get("extensions.lastbird.lbaddtracks").value;
    },
    EnableTrackDiscovery: function(){
        var item = document.getElementById("lastbird-track-discovery-item");
        item.setAttribute("checked", "true");
        
        Application.prefs.setValue("extensions.lastbird.lbaddtracks", true);
        this._TrackDiscovery = true;
    },
    DisableTrackDiscovery: function(){
        var item = document.getElementById("lastbird-track-discovery-item");
        item.setAttribute("checked", "false");
        
        Application.prefs.setValue("extensions.lastbird.lbaddtracks", false);
        this._TrackDiscovery = false;
    },
    
    
    
    AppendTrack: function(song){
        if (!gCurrentPlaylist.contains(song)) 
            gCurrentPlaylist.add(song);
    },
    getItemInfo: function(item){
        var str = item.getProperty(SBProperties.artistName) + " - " + item.getProperty(SBProperties.trackName);
        return str;
    },
    
    CreatePlaylist: function(name){
        var library = LibraryUtils.mainLibrary;
        var newlist = library.createMediaList("simple");
        newlist.name = name;
        return newlist;
    },
    SelectPlaylist: function(newlist){
        gBrowser.loadMediaList(newlist);
    },
    
    FindLocalSong: function(artist, trackName){
        var properties = Cc["@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"].createInstance(Ci.sbIMutablePropertyArray);
        
        properties.appendProperty(SBProperties.artistName, artist);
        properties.appendProperty(SBProperties.trackName, trackName);
        try {
            var tracks = LibraryUtils.mainLibrary.getItemsByProperties(properties);
            var enumerator = tracks.enumerate();
            while (enumerator.hasMoreElements()) {
                var item = enumerator.getNext();
                
                return item;
            }
        } 
        catch (e) {
        }
        return null;
    },
    FindLocalArtist: function(artist){
        var properties = Cc["@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"].createInstance(Ci.sbIMutablePropertyArray);
        
        properties.appendProperty(SBProperties.artistName, artist);
        try {
            var tracks = LibraryUtils.mainLibrary.getItemsByProperties(properties);
            var enumerator = tracks.enumerate();
            var ret = new Array();
            while (enumerator.hasMoreElements()) {
                var item = enumerator.getNext();
                ret.push(item);
            }
            return ret;
        } 
        catch (e) {
        }
        return null;
    },
    
    
    GetSimilarArtists: function(artistName){
        gLFM.apiCall('artist.getSimilar', {
            artist: artistName
        }, Lastbird.XML.DecodeArtists);
    },
    GetSimilarTracks: function(artistName, trackName){
        gLFM.apiCall('track.getSimilar', {
            artist: artistName,
            track: trackName
        }, Lastbird.XML.DecodeTracks);
    },
    GetTopTracks: function(artistName){
        gLFM.apiCall('artist.getTopTracks', {
            artist: artistName
        }, Lastbird.XML.DecodeTopTracks);
    },
    AppendSimilarArtists: function(names){
        var count = 0;
        for (i = 0; i < names.length; i++) {
            var songs = this.FindLocalArtist(names[i]);
            if (songs == null) 
                continue;
            for (j = 0; j < songs.length; j++) {
                count++;
                this.AppendTrack(songs[j]);
            }
        }
    },
    AppendTracks: function(names){
        var count = 0;
        for (i = 0; i < names.length; i++) {
            this.AppendTrackByName(names[i + 1], names[i]);
        }
    },

};


Lastbird.XML = {
    ToString: function(xml){
        var serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].createInstance(Components.interfaces.nsIDOMSerializer);
        var text = serializer.serializeToString(xml);
        return text;
    },
    DecodeArtists: function(success, xml){
        if (success) {
            try {
                var similarArtistNodes = gXPath.evaluate("//artist/name", xml, null, 7, null);
                var names = new Array();
                //                Msg(Lastbird.XML.ToString(xml));
                for (i = 0; i < similarArtistNodes.snapshotLength; i++) {
                    var similarArtist = similarArtistNodes.snapshotItem(i);
                    names[i] = similarArtist.textContent;
                }
                Lastbird.Controller.AppendSimilarArtists(names);
            } 
            catch (e) {
                Msg(e);
            }
        }
        else {
            Msg("last fm api call failed")
        }
    },
    DecodeTracks: function(success, xml){
        if (success) {
            try {
                var nodes = gXPath.evaluate("//track/name/text() | //track/artist/name/text()", xml, null, 7, null);
                var names = new Array();
                //              Msg(Lastbird.XML.ToString(xml));
                for (i = 0; i < nodes.snapshotLength; i++) {
                    var node = nodes.snapshotItem(i);
                    names[i] = node.textContent;
                }
                Lastbird.Controller.AppendTracks(names);
            } 
            catch (e) {
                Msg(e);
            }
        }
        else {
            Msg("last fm api call failed")
        }
    },
};

Lastbird.Listener = {

    onMediacoreEvent: function(ev){
    
        switch (ev.type) {
            case Components.interfaces.sbIMediacoreEvent.TRACK_CHANGE:
                var mediaItem = ev.data;
                Lastbird.Controller.OnTrackChanged(mediaItem);
                break;
            case Components.interfaces.sbIMediacoreEvent.VIEW_CHANGE:
                var view = ev.data;
                Lastbird.Controller.OnViewChanged(view);
                break;
			
        }
    }
};



window.addEventListener("load", function(e){
    Lastbird.Controller.onLoad(e);
}, false);
window.addEventListener("unload", function(e){
    Lastbird.Controller.onUnLoad(e);
}, false);
